package com.odata.mediawiki;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import com.odata.mediawiki.Constants;
import com.odata.mediawiki.Wiki;
import com.odata.mediawiki.Wiki.Revision;

/**
 * A helper class that interacts with Wiki API to provide basic functionality of adding, retrieving, updating
 * the information of Media Wiki pages, categories and other media wiki site details.
 *
 * @author Aashish Salokhe
 * @author Kedar Deshpande
 * @since 1.0
 */
@Copyright
public class WikiEntityGetters {

	/**
	 * Parameters required to initialize the Wiki object.
	 */
	private static String[] params;

	/**
	 * The main Wiki object to communicate with Media Wiki API.
	 */
	private static Wiki wikiObject;

	static{
		params = MediaWikiProducer.getParameter();
		if(params[1].isEmpty())
			wikiObject = new Wiki(params[0]);
		else
			wikiObject = new Wiki(params[0],params[1]);
	}

	/**
	 * Gets the contents of the given page.
	 * @param pageTitle Title of the page.
	 * @return String text of the page.
	 * @throws IOException if network error occurs.
	 * @throws Exception if any other error occurs.
	 */
	public static String getPage(String pageTitle) throws IOException, Exception {
		if(pageTitle == null || pageTitle.isEmpty())
			throw new NullPointerException("pageTitle cannot be empty : getPage");		
		return wikiObject.getPageText(pageTitle);
	}

	/**
	 * Gets the names of the pages that fall under given category.
	 * @param categoryTitle Name of the category.
	 * @param subcat When true, the result includes the pages having subcategories as well.
	 * @return Array of names of pages.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static String[] getCategory(String categoryTitle, boolean subcat) throws IOException, Exception {
		if(categoryTitle == null || categoryTitle.isEmpty())
			throw new NullPointerException("categoryTitle cannot be empty: getCategory");
		return wikiObject.getCategoryMembers(categoryTitle, subcat, new int[]{});
	}

	/**
	 * Gets the specific revision object for the given revision Id.
	 * @param revisionID ID of the revision to retrieve.
	 * @return Revision object.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static Revision getPageRevision(long revisionID) throws IOException, Exception {
		return wikiObject.getRevision(revisionID);
	}

	/**
	 * Gets the information about the given file.
	 * @param fileName Name of the file to retrieve.
	 * @return A map of property name vs. value.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static HashMap<String,Object> getFile(String fileName) throws IOException, Exception {
		if(fileName == null || fileName.isEmpty())
			throw new NullPointerException("fileName cannot be empty : getFile");
		return wikiObject.getFileMetadata(fileName);
	}

	/**
	 * Gets the details about the particular media wiki site.
	 * @return A map of property name vs. value.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static HashMap<String, Integer> getSite() throws IOException, Exception {
		return wikiObject.getSiteStatistics();
	}

	/**
	 * Gets names of all the pages on the media wiki site.
	 * @return Array of string names.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static String[] getPages() throws IOException, Exception {
		return wikiObject.listPages("", null, 0);
	}

	/**
	 * Gets names of all the categories on the media wiki site.
	 * @return Array of string names.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static String[] getCategories() throws IOException, Exception {
		return wikiObject.getCategories();
	}

	/**
	 * Gets names of all the files on the media wiki site.
	 * @return Array of string names.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static String[] getAllFiles() throws IOException, Exception {
		return wikiObject.getAllFiles();
	}

	/**
	 * Gets the details about the particular media wiki site.
	 * @return A map of property name vs. value.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static HashMap<String,Integer> getSiteData() throws IOException, Exception {
		return wikiObject.getSiteStatistics();
	}

	/**
	 * Gets detailed information of the given page.
	 * @param page Name of the page.
	 * @return Map of property name vs. value.
	 * @throws IOException if network error occurs.
  	 * @throws Exception if any other error occurs.
	 */
	public static HashMap<Object, Object> getPageInfo(String page) throws IOException, Exception {
		return wikiObject.getPageInfo(page);
	}

	/**
	 * Gets all the links that are present in the contents of the given page.
	 * @param pageTitle Name of the page.
	 * @return Array of strings (links)
	 * @throws Exception if some error occurs.
	 */
	public static String[] getAllLinks(String pageTitle) throws Exception {
		return wikiObject.getLinksOnPage(pageTitle);
	}

	/**
	 * Gets all the language links that are present in the contents of the given page.
	 * @param pageTitle Name of the page.
	 * @return Map of formal language code vs. name of the page on the external wiki linked to.
	 * @throws Exception if some error occurs.
	 */
	public static Map<String, String> getLangLinks(String pageTitle) throws Exception {
		return wikiObject.getInterWikiLinks(pageTitle);
	}

	/**
	 * Gets all the categories that given page belongs to.
	 * @param pageTitle Name of the page.
	 * @return Array of strings (category names)
	 * @throws Exception if some error occurs.
	 */
	public static String[] getPageCategories(String pageTitle) throws Exception {
		return wikiObject.getCategories(pageTitle);
	}

	/**
	 * Gets all the Images that are present in the contents of the given page.
	 * @param pageTitle Name of the page.
	 * @return Array of strings (names of images)
	 * @throws Exception if some error occurs.
	 */
	public static String[] getPageImages(String pageTitle) throws Exception {
		return wikiObject.getImagesOnPage(pageTitle);
	}

	/**
	 * Modifies the given page with given text contents.
	 * @param pageTitle Name of the page.
	 * @param text modified contents of the page.
	 * @param summary a short summary.
	 * @throws Exception if some error occurs.
	 */
	public static void editPage(String pageTitle,String text, String summary) throws Exception {
		wikiObject.edit(pageTitle, text, summary);
	}

	/**
	 * Gets all the revisions of the given page.
	 * @param pageTitle Name of the page.
	 * @return Array of revision objects.
	 * @throws Exception if some error occurs.
	 */
	public static Revision[] getAllRevisions(String pageTitle) throws Exception {
		return wikiObject.getPageHistory(pageTitle);
	}

	/**
	 * Gets the names of all the pages that have link to the given page.
	 * @param pageTitle Name of the page.
	 * @return Array of strings (names of pages).
	 * @throws Exception if some error occurs.
	 */
	public static String[] getLinksToHere(String pageTitle) throws Exception {
		return wikiObject.whatLinksHere(pageTitle, 0);
	}

	/**
	 * Creates or edits the given page having the given text contents.
	 * @param pageTitle Name of the page.
	 * @param pageContent Text contents of the page.
	 * @return The page contents.
	 * @throws Exception if some error occurs.
	 */
	public static String createPage(String pageTitle, String pageContent) throws Exception {
		wikiObject.edit(pageTitle, pageContent, "");
		return getPage(pageTitle);
	}
}
